import Koa from 'koa';
import koaJwt from 'koa-jwt';
import KoaCors from '@koa/cors';
import { useKoaServer, useContainer, getMetadataArgsStorage } from 'routing-controllers';
import { dataSource } from './utils/orm';
import { jwtConfig, serveConfig, unlessConfig } from './config/app.config';
import { Container } from 'typedi';
import { logger } from './utils/logger';

/**
 * 服务启动
 */
export async function AppServer() {
  const app = new Koa();

  // 允许跨域设置
  app.use(KoaCors());

  // 401 handling
  app.use(async (ctx, next) => {
    try {
      return await next();
    } catch (err: any) {
      if (err.status === 401) {
        ctx.status = 401;
        ctx.body = {
          code: err.status,
          message: err.originalError ? err.originalError.message : err.message,
        };
      } else {
        throw err;
      }
    }
  });

  // 启用jwt
  app.use(koaJwt({ secret: jwtConfig.secret }).unless({ path: unlessConfig.path }));

  // 通知 routing-controllers 使用typedi的IOC容器
  useContainer(Container, { fallback: true, fallbackOnErrors: true });

  // 注册服务
  useKoaServer(app, serveConfig.options);

  // 端口监听
  app.listen(serveConfig.port, () => {
    logger.info(`服务正在运行: http://localhost:${serveConfig.port}${serveConfig.prefix}`);
    if (serveConfig.debug) {
      AppRoute();
    }
  });

  return app;
}

/**
 * 数据库连接
 */
export async function AppSource() {
  try {
    const conn = await dataSource.initialize();
    logger.info('数据库连接成功...');
    return conn;
  } catch (error) {
    logger.error('数据库连接失败...', error);
  }
}

/**
 * 路由信息
 */
export async function AppRoute() {
  logger.info('============================================================');
  // const routes: Record<string, { type: string; route: string }[]> = {};
  const { controllers, actions } = getMetadataArgsStorage();
  controllers.forEach((controller) => {
    // routes[controller.target.name] = [];
    actions.forEach((action) => {
      if (action.target.name === controller.target.name) {
        // routes[controller.target.name].push({
        //   type: action.type,
        //   route: `${controller.route}${action.route}`,
        // });
        logger.info(`${action.type.padEnd(6, ' ')} ${controller.route}${action.route}`);
      }
    });
  });
  logger.info('============================================================');
}
